package com.gitee.zhanyao.codebase.java.file.poi.word;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhanyao
 */
@Slf4j
public class WordUtil {

    /**
     * 读取 word 文件
     *
     * @param filePath
     * @return
     * @throws Exception
     */
    public static XWPFDocument readFile(String filePath) throws Exception {
        File file = ResourceUtils.getFile(filePath);
        try (InputStream inputStream = new FileInputStream(file)) {
            return new XWPFDocument(inputStream);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 将 XWPFDocument 转换为 ByteArrayOutputStream，用于下载
     * 用法：
     * @param xwpfDocument
     * @return
     * @throws IOException
     */
    public static InputStream getByteArrayInputStream(XWPFDocument xwpfDocument) throws IOException {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        xwpfDocument.write(stream);
        return new ByteArrayInputStream(stream.toByteArray());
    }

    /**
     * word 拼接
     *
     * @param src
     * @param append
     * @throws Exception
     */
    public static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();
        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID
        Map<String, String> map = new HashMap<>();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }
        appendBody(src1Body, src2Body, map);
    }

    public static void appendBody(CTBody src, CTBody append, Map<String, String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);

        String srcString = src.xmlText();
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));

        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        //将两个文档的xml内容进行拼接
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src.set(makeBody);
    }

    /**
     * 解决文件名为中文无法显示问题
     *
     * @param name
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String changeNameToDownload(String name) throws UnsupportedEncodingException {
        return new String(name.getBytes("UTF-8"), "ISO-8859-1");
    }
}
